<?php

namespace Beike\Seller\Http\Controllers;

use Beike\Admin\Http\Requests\ProductRequest;
use Beike\Admin\Http\Resources\ProductAttributeResource;
use Beike\Admin\Repositories\TaxClassRepo;
use Beike\Libraries\Weight;
use Beike\Repositories\CategoryRepo;
use Beike\Repositories\LanguageRepo;
use Beike\Seller\Http\Resources\ProductResource;
use Beike\Seller\Models\Product;
use Beike\Seller\Repositories\ProductRepo;
use Beike\Seller\Repositories\SellerCategoryRepo;
use Beike\Seller\Services\ProductService;
use Beike\Repositories\FlattenCategoryRepo;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ProductController extends Controller
{
    protected string $defaultRoute = 'products.index';

    /**
     * @param Request $request
     * @return array|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
     */
    public function index(Request $request)
    {
        $requestData    = $request->all();
        if (! isset($requestData['sort'])) {
            $requestData['sort']  = 'products.updated_at';
            $requestData['order'] = 'desc';
        }
        $productList    = ProductRepo::list($requestData);

        $products       = ProductResource::collection($productList);
        $productsFormat =  $products->jsonSerialize();

        $data = [
            'categories'      => CategoryRepo::flatten(locale()),
            'products_format' => $productsFormat,
            'products'        => $products,
            'type'            => 'products',
        ];

        if ($request->expectsJson()) {
            return $productsFormat;
        }

        return view('seller::pages.products.index', $data);
    }

    /**
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\Resources\Json\AnonymousResourceCollection
     */
    public function trashed(Request $request)
    {
        $requestData            = $request->all();
        $requestData['trashed'] = true;
        $productList            = ProductRepo::list($requestData);
        $products               = ProductResource::collection($productList);
        $productsFormat         =  $products->jsonSerialize();

        $data = [
            'categories'      => CategoryRepo::flatten(locale()),
            'products_format' => $productsFormat,
            'products'        => $products,
            'type'            => 'trashed',
        ];

        if ($request->expectsJson()) {
            return $products;
        }

        return view('seller::pages.products.index', $data);
    }

    /**
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
     */
    public function create(Request $request)
    {
        return $this->form($request, new Product());
    }

    /**
     * @param ProductRequest $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function store(ProductRequest $request)
    {
        try {
            DB::beginTransaction();
            $requestData = $request->all();
            $requestData['skus'] = array_map(function ($item) {
                $item['sku'] = 'S' . current_seller_user()->seller_id . '-' . $item['sku'];
                return $item;
            }, $requestData['skus']);
            $actionType  = $requestData['action_type'] ?? '';
            $product     = (new ProductService)->create($requestData);

            DB::commit();
            return redirect()->to($actionType == 'stay' ? seller_route('products.create') : seller_route('products.index'))->with('success', trans('common.created_success'));
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect(seller_route('products.create'))
                ->withInput()
                ->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * @param Request $request
     * @param int     $id
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
     */
    public function edit(Request $request, int $id)
    {
        $product = Product::find($id);

        return $this->form($request, $product);
    }

    /**
     * @param ProductRequest $request
     * @param int            $id
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function update(ProductRequest $request, int $id)
    {
        try {
            DB::beginTransaction();
            $product     = Product::find($id);
            $requestData = $request->all();
            $requestData['skus'] = array_map(function ($item) {
                $item['sku'] = 'S' . current_seller_user()->seller_id . '-' . $item['sku'];
                return $item;
            }, $requestData['skus']);
            $actionType  = $requestData['action_type'] ?? '';
            $product     = (new ProductService)->update($product, $requestData);
            DB::commit();

            return redirect()->to($actionType == 'stay' ? seller_route('products.edit', [$product->id]) : seller_route('products.index'))->with('success', trans('common.updated_success'));
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect(seller_route('products.edit', $product))->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * @param Request $request
     * @param int     $id
     * @return array
     */
    public function destroy(Request $request, int $id)
    {
        Product::find($id)->delete();

        return json_success(trans('common.deleted_success'));
    }

    /**
     * @param Request $request
     * @return bool[]
     */
    public function restore(Request $request)
    {
        $productId = $request->id ?? 0;
        Product::withTrashed()->find($productId)->restore();

        return ['success' => true];
    }

    /**
     * @param Request $request
     * @param Product $product
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
     */
    protected function form(Request $request, Product $product)
    {
        if ($product->id) {
            $descriptions       = $product->descriptions->keyBy('locale');
            $categoryIds        = $product->categories->pluck('id')->toArray();
            $sellerCategoryIds  = $product->sellerCategories->pluck('id')->toArray();
            $product->load('brand', 'attributes');
        }

        $taxClasses = TaxClassRepo::getList();
        array_unshift($taxClasses, ['title' => trans('admin/builder.text_no'), 'id' => 0]);
        $sellerCategories = SellerCategoryRepo::list(current_seller_user()->seller_id);

        $data = [
            'product'               => $product,
            'product_approve'       => current_seller_user()->seller->product_approve,
            'descriptions'          => $descriptions       ?? [],
            'category_ids'          => $categoryIds        ?? [],
            'seller_category_ids'   => $sellerCategoryIds  ?? [],
            'product_attributes'    => ProductAttributeResource::collection($product->attributes),
            'relations'             => ProductResource::collection($product->relations)->resource,
            'languages'             => LanguageRepo::all(),
            'tax_classes'           => $taxClasses,
            'system_currency'           => system_setting('base.currency', 'USD'),
            'system_weight'           => system_setting('base.weight', 'kg'),
            'weight_classes'        => Weight::getWeightUnits(),
            'source'                => [
                'flatten_categories' => FlattenCategoryRepo::getCategoryList(),
                'categories'         => CategoryRepo::flatten(locale(), false),
                'seller_categories' => $sellerCategories,
            ],
            '_redirect'          => $this->getRedirect(),
        ];

        return view('seller::pages.products.form.form', $data);
    }

    /**
     * @param int $id
     * @return array
     */
    public function name(int $id)
    {
        $name = ProductRepo::getName($id);

        return json_success(trans('common.get_success'), $name);
    }

    /**
     * 根据商品ID批量获取商品名称
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function getNames(Request $request)
    {
        $productIds = explode(',', $request->get('product_ids'));
        $name       = ProductRepo::getNames($productIds);

        return json_success(trans('common.get_success'), $name);
    }

    /**
     * @param Request $request
     * @return array
     */
    public function autocomplete(Request $request)
    {
        $products = ProductRepo::autocomplete($request->get('name') ?? '');

        return json_success(trans('common.get_success'), $products);
    }

    /**
     * @param Request $request
     * @return array
     */
    public function updateStatus(Request $request)
    {
        ProductRepo::updateStatusByIds($request->get('ids'), $request->get('status'));

        return json_success(trans('common.updated_success'), []);
    }

    /**
     * @param Request $request
     * @return array
     */
    public function destroyByIds(Request $request)
    {
        $productIds = $request->get('ids');
        ProductRepo::DeleteByIds($productIds);

        return json_success(trans('common.deleted_success'), []);
    }

    /**
     * @return void
     */
    public function trashedClear()
    {
        ProductRepo::forceDeleteTrashed();
    }
}
